/***************************************************************************
 *   Copyright (C) 2009 by Rysiek Król,,,   				   *
 *   rysiek.krol@gmail.com   						   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "filesoperations.h"

#include "picturemanager.h"
#include "picturelistwidgetitem.h"
#include "fileoperationshandler.h"
#include "imagereader.h"
#include "renamedialog.h"
#include "viewerevent.h"
#include "viewerconstants.h"
#include "utils.h"

#include <QMessageBox>
#include <QFileDialog>
#include <QInputDialog>
#include <QLineEdit>
#include <QDirModel>
#include <QTreeView>
#include <QListWidget>
#include <QClipboard>
#include <QUrl>

/**
 * Class Constructor
 * @param parent PictureManager
 */
FilesOperations::FilesOperations(QObject *parent)
  : QObject(parent){
  this->manager = dynamic_cast<PictureManager*>(parent);
  this->cutAction = false;
}

/**
 * Destructor
 */
FilesOperations::~FilesOperations()
{
}

/**
* Hendles copy files Action
*/
void FilesOperations::copyFilesSlot(FilesOperations::ActionSource source)
{
    QString newDir;
    QFileDialog dialog(this->manager);
    dialog.setDirectory(*this->manager->getCurDir());
    dialog.setFileMode(QFileDialog::DirectoryOnly );
    if (dialog.exec())
    {
        newDir = dialog.directory().absolutePath ();
        new FileOperationsHandler(this->manager, FileOperationsHandler::Copy, this->fillFileList(source), newDir);
    }
}

/**
* Hendles move files Action
*/
void FilesOperations::moveFilesSlot(FilesOperations::ActionSource source)
{
    QString newDir;
    QFileDialog dialog(this->manager);
    dialog.setDirectory(*this->manager->getCurDir());
    dialog.setFileMode(QFileDialog::DirectoryOnly );
    if (dialog.exec())
    {
        this->manager->getItsReader()->setIsActive(false);
        newDir = dialog.directory().absolutePath ();
        new FileOperationsHandler(this->manager, FileOperationsHandler::Move, this->fillFileList(source), newDir);
    }
}

/**
* Hendles delete files Action
*/
void FilesOperations::deleteFilesSlot(FilesOperations::ActionSource source)
{
    QMessageBox msgBox;
    msgBox.setStandardButtons(QMessageBox::No|QMessageBox::Yes);
    msgBox.setText(tr("Are you sure to delete selected files?"));
    msgBox.setWindowTitle(tr("Deleting files..."));
    msgBox.setIcon(QMessageBox::Question);
    if ( msgBox.exec()==QMessageBox::Yes )
    {
        this->manager->getItsReader()->setIsActive(false);
        new FileOperationsHandler(this->manager, FileOperationsHandler::Delete, this->fillFileList(source));

    }
}

/**
 * Handles delete operation triggered by tree widget
 */
void FilesOperations::deleteTreeSlot()
{
    this->deleteFilesSlot(FilesOperations::TreeWidget);
}

/**
 * Handles copy operation triggered by tree widget
 */
void FilesOperations::copyTreeSlot()
{
    this->copyFilesSlot(FilesOperations::TreeWidget);
}

/**
 * Handles move action triggered by tree widget
 */
void FilesOperations::moveTreeSlot()
{
    this->moveFilesSlot(FilesOperations::TreeWidget);
}

/**
* Handles make directory Action
*/
void FilesOperations::makeDirectory(FilesOperations::ActionSource source)
{
    bool ok;
    QString text = QInputDialog::getText(this->manager, tr("Make new directory"), tr("Enter directory name"), QLineEdit::Normal, QDir::home().dirName(), &ok);
    if (ok && !text.isEmpty()) new FileOperationsHandler(this->manager, FileOperationsHandler::MakeDir, this->fillFileList(source), text);
}

/**
 * Handles rename operation triggered by tree widget
 */
void FilesOperations::renameTreeSlot()
{
    this->renameDialog(FilesOperations::TreeWidget);
}

/**
 * Renameing files
 */
void FilesOperations::renameDialog(FilesOperations::ActionSource source)
{
    QString newFileName;
    RenameDialog dialog ( this->manager );
    if ( dialog.exec() )
    {
        if (source == FilesOperations::BrowserWidget) new FileOperationsHandler(this->manager, FileOperationsHandler::Rename, this->fillFileList(), dialog.getText());
        if (source == FilesOperations::TreeWidget)
        {
            QFileInfo fileInfo =(dynamic_cast<QDirModel*> (this->manager->getTreeWidget()->model()))->fileInfo( this->manager->getTreeWidget()->currentIndex() );
            QDir dir = fileInfo.dir();
            dir.rename(fileInfo.fileName(), dialog.getText());
            this->manager->getCurDir()->cd(dir.filePath(dialog.getText()));
            QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::ForceReload ) ) );
        }
    }
}

/**
* Fill in list of selected items to copy/delete/move procedures
*/
QList<QFileInfo*>* FilesOperations::fillFileList(FilesOperations::ActionSource source)
{
    QList<QFileInfo*> *lista = new QList<QFileInfo*>();
    if (source == FilesOperations::BrowserWidget)
    {
        QList<QListWidgetItem *> selectedItemsIndex = this->manager->getListWidget()->selectedItems ();
        if (selectedItemsIndex.count()>0)
        {
            //Iteracja i dodawanie plików na początek listy
            QListIterator<QListWidgetItem *> iterator(selectedItemsIndex);
            iterator.toFront();
            while (iterator.hasNext())
            {
                QFileInfo *item = new QFileInfo(dynamic_cast<PictureListWidgetItem*>(iterator.next())->getFile());
                if (!item->isDir())
                {
                    lista->append(item);
                }
                else
                {
                    delete item;
                };
            }
            //iteracja i dodawanie katalogów na koniec listy
            iterator.toFront();
            PictureListWidgetItem *item = dynamic_cast<PictureListWidgetItem*>(iterator.next());
            if (item->text()!=".. (up)" && item->getFile().isDir())
		generateListFromDir(lista, new QDir(item->getFile().absoluteFilePath()));
            while (iterator.hasNext())
            {
                QFileInfo *item = new QFileInfo(dynamic_cast<PictureListWidgetItem*>(iterator.next())->getFile());
                if (item->isDir())
                {
                    generateListFromDir(lista, new QDir(item->absoluteFilePath()));
                }
                else
                {
                    delete item;
                };
            }
        }
    }
    else
    {
        QFileInfo *fileInfo =new QFileInfo((dynamic_cast<QDirModel*> (this->manager->getTreeWidget()->model()))->fileInfo( this->manager->getTreeWidget()->currentIndex()));
        generateListFromDir(lista, new QDir(fileInfo->absoluteFilePath()));
	delete fileInfo;
    }
    return lista;
}

/*
 * Generates Files list from given directory
 */
QList< QFileInfo * > * FilesOperations::generateListFromDir(QList< QFileInfo *> *lista ,QDir * dir)
{
    ViewerConstants constanst;
    QFileInfoList fileList = dir->entryInfoList(constanst.getFilters(), QDir::Files);
    QListIterator<QFileInfo> iterator(fileList);
    QFileInfo item;
    lista->append(new QFileInfo(dir->absolutePath()));
    //Adding files to list
    while (iterator.hasNext())
    {
        item = iterator.next();
        lista->append(new QFileInfo(item));
    }
    QFileInfoList dirList = dir->entryInfoList(constanst.getFilters(), QDir::Files);
    dirList = dir->entryInfoList(QStringList(), QDir::Dirs|QDir::NoDotAndDotDot);
    QListIterator<QFileInfo> dirIterator(dirList);
    //adding directory
    while (dirIterator.hasNext())
    {
        item = dirIterator.next();
        generateListFromDir(lista, new QDir(item.absoluteFilePath()));
    }
    delete dir;
    return lista;
}

/**
  * Handles copy action
  */
void FilesOperations::copySlot(){
     QList<QUrl> urlList;
     QList<QListWidgetItem *> selectedList = this->manager->getListWidget()->selectedItems();
     //generating QUrl's list from selected items
     for(QList<QListWidgetItem *>::const_iterator i = selectedList.begin(); i != selectedList.end();i++){
         PictureListWidgetItem *item = dynamic_cast<PictureListWidgetItem*>(*i);
         if(item->text()!=".. (up)"){
            urlList.append(QUrl::fromLocalFile(item->getFile().canonicalFilePath()));
         } //if
     }//for
     //Send Url's list to clipboard
     if(!urlList.isEmpty()){
           QMimeData *mimeData = new QMimeData();
           mimeData->setUrls(urlList);
           QClipboard *clipboard = QApplication::clipboard();
           clipboard->setMimeData(mimeData, QClipboard::Clipboard);
     }//if
}

/**
  * Handles cut action
  */
void FilesOperations::cutSlot(){
    this->cutAction = true;
    this->copySlot();
}

/**
  * Handles paste action
  */
void FilesOperations::pasteSlot(){
    QClipboard *clipboard = QApplication::clipboard();
    const QMimeData *mimeData = clipboard->mimeData();
    if(mimeData->hasUrls()){
        QList<QFileInfo*>* fileList = new QList<QFileInfo*>();
        QList<QFileInfo*>* dirList = new QList<QFileInfo*>();
        QList<QUrl> *urlList = new QList<QUrl>(mimeData->urls());
        //converts Url list to QFileInfo
        for(QList<QUrl>::const_iterator i = urlList->begin(); i!=urlList->end();i++){
            QFileInfo *file = new QFileInfo(i->toLocalFile());
            if(file->exists()){
                if(file->isDir()){
                    dirList->append(file);
                } else {
                    fileList->append(file);
                } //if
            }//if
        }//for
        //Generating files from copied directories
        for(QList<QFileInfo*>::const_iterator i = dirList->begin(); i!=dirList->end();i++){
            this->generateListFromDir(fileList, new QDir(((QFileInfo*)*i)->absoluteFilePath()));
        } //for
        if(!fileList->isEmpty()){
            FileOperationsHandler::OperationType paseOperation = FileOperationsHandler::Copy;
            if(this->cutAction) paseOperation = FileOperationsHandler::Move;
            new FileOperationsHandler(this->manager, paseOperation, fileList, this->manager->getCurDir()->absolutePath());
        }
        delete urlList;
        delete dirList;
    }//if
    this->cutAction = false;
}


